package person.bluext.singlegateway.frame;

import lombok.extern.slf4j.Slf4j;
import person.bluext.singlegateway.common.exception.HandleMethodNotFoundException;
import person.bluext.singlegateway.frame.model.ExecuteBean;
import person.bluext.singlegateway.frame.model.Response;

import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Description : Basic handler
 * <p>Every handler should extends this class</p>
 *
 * @author : bluext
 */
@Slf4j
public abstract class BaseHandler {

    private final Map<String, Method> methodMap = new HashMap<>();

    @PostConstruct
    protected void init() {
        Class clazz = this.getClass();
        log.info(">> Start to initialize handler instance -> ClassName: {}", clazz.getName());

        String className = clazz.getSimpleName();
        Method[] methods = clazz.getDeclaredMethods();
        for (Method m : methods) {
            m.setAccessible(true);
            methodMap.put(m.getName(), m);
            log.info(">> Start to cache method -> {}.{}", className, m.getName());
        }
    }

    /**
     * 通过反射执行指定方法
     *
     * @param executeBean 方法执行要素
     * @return 执行结果
     * @throws ReflectiveOperationException
     */
    public Response execute(ExecuteBean executeBean) throws ReflectiveOperationException {
        Method method = this.methodMatching(executeBean.getFuncName());
        Object[] args = new Object[]{executeBean.getParamStr()};
        return (Response) method.invoke(this, args);
    }

    /**
     * 根据版本号匹配Method对象
     *
     * @param funcName 方法名
     * @return Method对象
     */
    protected Method methodMatching(String funcName) {
        if (methodMap.containsKey(funcName)) {
            return methodMap.get(funcName);
        }

        log.info(">> 没有匹配到Method对象");
        throw new HandleMethodNotFoundException(funcName);
    }
}
